#!/usr/bin/python
# -*- coding: utf-8 -*-

import json
import pathlib
import re
import math
import pandas as pd

code_num = -1

strategy = {}
# 指向下一个index （完成逻辑后+1）
now = 0
# 当前状态是否为买 true:可买
status_buy = True
# 自身资产
asset_own = 10000
# 股市资产
asset_share = 0
asset_all = 10000
# 持股数
stock_num = 0
data_all = []
data_open = []
data_close = []
data_highest = []
data_lowest = []
data_MA5 = []
data_MA10 = []
data_MA20 = []
data_MA30 = []
data_increase = []
data_time = []

data_trend = []
data_max_after_buy = []

buy_arr = []
sell_arr = []
mark_point_arr = []
# 每时刻的资产数据
asset_own_arr = []
stock_num_arr = []
asset_share_arr = []
asset_all_arr = []
# 上次进行买或卖的index
last_buy_i = 0
last_sell_i = 0
last_buy_or_sell_i = 0

# 测试用的（正式不用）
data_frame = None


# 根据获取的策略初始化数据
def judge_init(code):
    # 股票数据初始化
    global code_num
    global now
    global data_all
    global data_close
    global data_open
    global data_highest
    global data_lowest
    global data_trend
    global data_MA5
    global data_MA10
    global data_MA20
    global data_MA30
    global data_increase
    global data_time
    code_num = code
    data_all = get_data(code)
    data_open = data_all['开盘']
    data_close = data_all['收盘']
    data_highest = data_all['最高']
    data_lowest = data_all['最低']
    data_time = data_all['日期']
    data_MA5 = data_close.rolling(5).mean().round(2).bfill()
    data_MA10 = data_close.rolling(10).mean().round(2).bfill()
    data_MA20 = data_close.rolling(20).mean().round(2).bfill()
    data_MA30 = data_close.rolling(30).mean().round(2).bfill()
    data_increase = ((data_all['收盘'] - data_all['开盘']) / data_all['开盘']).round(4)
    # 将数据保存到csv
    s_close = pd.Series(data_close, name='close')
    s_open = pd.Series(data_open, name='open')
    s_highest = pd.Series(data_highest, name='highest')
    s_lowest = pd.Series(data_lowest, name='lowest')
    # s_trend = pd.Series(data_trend, name='trend')
    global data_frame
    data_frame = pd.DataFrame({'open': s_open, 'close': s_close, 'lowest': s_lowest, 'highest': s_highest})
    data_frame.to_csv('data_frame.csv')

    # 其他数据格式化
    global asset_own
    global asset_share
    asset_own = 100000
    asset_share = 0


def get_data(code):
    return pd.read_csv('web/stockDetail/' + code + '/data.csv')


def get_strategy(strategy_name):
    global strategy
    strategy_file = open('json/strategy_t.json', 'r')
    strategy = json.load(strategy_file)
    return strategy["strategy"][strategy_name]


# 返回处理open数据后的logic_str
# open(2) 两天前的open
def get_open_str(logic_str):
    global now
    logic_str = logic_str.replace('{open}', '(' + str(data_open[now]) + ')')
    r = re.compile(r'{open\((.*?)\)}')
    arr = re.findall(r, logic_str)
    # item : 括号里的内容 arr: 数组（可能有多个{open()}）
    for item in arr:
        target_i = now
        if item != "":
            target_i = now - int(item) if (now - int(item)) >= 0 else 0
        logic_str = r.sub('(' + str(data_open[target_i]) + ')', logic_str, count=1)
    return logic_str


def get_close_str(logic_str):
    global now
    logic_str = logic_str.replace('{close}', '(' + str(data_close[now]) + ')')
    r = re.compile(r'{close\((.*?)\)}')
    arr = re.findall(r, logic_str)
    # item : 括号里的内容 arr: 数组（可能有多个{open()}）
    for item in arr:
        target_i = now
        if item != "":
            target_i = now - int(item) if (now - int(item)) >= 0 else 0
        logic_str = r.sub('(' + str(data_close[target_i]) + ')', logic_str, count=1)
    return logic_str


def get_lowest_str(logic_str):
    global now
    logic_str = logic_str.replace('{lowest}', '(' + str(data_lowest[now]) + ')')
    r = re.compile(r'{lowest\((.*?)\)}')
    arr = re.findall(r, logic_str)
    # item : 括号里的内容 arr: 数组（可能有多个{open()}）
    for item in arr:
        target_i = now
        if item != "":
            target_i = now - int(item) if (now - int(item)) >= 0 else 0
        logic_str = r.sub('(' + str(data_lowest[target_i]) + ')', logic_str, count=1)
    return logic_str


def get_highest_str(logic_str):
    global now
    logic_str = logic_str.replace('{highest}', '(' + str(data_highest[now]) + ')')
    r = re.compile(r'{highest\((.*?)\)}')
    arr = re.findall(r, logic_str)
    # item : 括号里的内容 arr: 数组（可能有多个{open()}）
    for item in arr:
        target_i = now
        if item != "":
            target_i = now - int(item) if (now - int(item)) >= 0 else 0
        logic_str = r.sub('(' + str(data_highest[target_i]) + ')', logic_str, count=1)
    return logic_str


# 计算趋势是否
def count_trend(days):
    before = (now - days) if (now - days) >= 0 else 0
    return (data_close[now] - data_close[before]) / data_close[before]


# trend(n)
# 获取趋势(当天收盘价-n天前的收盘价)/n天前收盘价
def get_trend_str(logic_str):
    r = re.compile(r'{trend\((.*?)\)}')
    arr = re.findall(r, logic_str)
    # item: 括号内的天数
    for item in arr:
        # 默认1天前
        target_i = 1
        if item != "":
            target_i = int(item)
        logic_str = r.sub('(' + str(count_trend(target_i)) + ')', logic_str, count=1)
    return logic_str


# 距离上次买入后的最大值
def get_after_buy_max_str(logic_str):
    r = re.compile(r'{max_after_buy.*?}')
    global last_buy_i
    global now
    get_max = pd.Series(data_close).loc[last_buy_i:now].max()
    logic_str = r.sub('(' + str(get_max) + ')', logic_str)
    return logic_str


# MA MA(5) 当天的5日均线
def get_MA_str(logic_str):
    global data_close
    r = re.compile(r'{MA\((.*?)\)}')
    arr = re.findall(r, logic_str)
    # item: days: MA(days)
    for item in arr:
        before = (now - int(item)) if (now - int(item)) >= 0 else 0
        data_section = data_close[before:now + 1]
        d = sum(data_section) / (now - before + 1)
        logic_str = r.sub('(' + str(d) + ')', logic_str, count=1)
    return logic_str


def get_MA5_str(logic_str):
    global data_MA5
    # r_com = re.compile(r'{MA5()}')
    logic_str = logic_str.replace('{MA5}', '(' + str(data_MA5[now]) + ')')
    logic_str = logic_str.replace('{MA5()}', '(' + str(data_MA5[now]) + ')')
    r = re.compile(r'{MA5\((.*?)\)}')
    arr = re.findall(r, logic_str)
    # item : days
    for item in arr:
        target = (now - int(item)) if (now - int(item)) > 0 else 0
        logic_str = r.sub('(' + str(data_MA5[target]) + ')', logic_str, count=1)
    return logic_str


def get_increase_str(logic_str):
    global data_increase
    logic_str = logic_str.replace('{increase}', '(' + str(data_increase[now]) + ')')
    logic_str = logic_str.replace('{increase()}', '(' + str(data_increase[now]) + ')')
    r = re.compile(r'{increase\((.*?)\)}')
    arr = re.findall(r, logic_str)
    for item in arr:
        target = (now - int(item)) if (now - int(item)) > 0 else 0
        logic_str = r.sub('(' + str(data_increase[target]) + ')', logic_str, count=1)
    return logic_str


# ----------------------------------
# 分界线 ↑:获取工具  ↓：逻辑相关
# ----------------------------------


# 先替换所有变量，再计算
# 返回值为bool
# "{open}*2>{close}*2", "{trend(5)>0.05}"
def logic_judge(logic_str):
    logic_str = get_open_str(logic_str)
    logic_str = get_close_str(logic_str)
    logic_str = get_lowest_str(logic_str)
    logic_str = get_highest_str(logic_str)
    logic_str = get_trend_str(logic_str)
    logic_str = get_after_buy_max_str(logic_str)
    logic_str = get_MA_str(logic_str)
    logic_str = get_MA5_str(logic_str)
    logic_str = get_increase_str(logic_str)
    # print(logic_str)

    logic_return = eval(logic_str)
    return logic_return


# 第i天买入
def buy_func(i):
    global data_close
    global asset_share
    global asset_own
    global stock_num
    global last_buy_i
    global last_buy_or_sell_i
    last_buy_i = i
    last_buy_or_sell_i = i
    stock_price = data_close[i]
    stock_num = math.floor(asset_own / stock_price)
    asset_share = stock_num * stock_price
    asset_own = asset_own % stock_price


# 第i天卖
def sell_func(i):
    global data_close
    global asset_share
    global asset_own
    global stock_num
    global last_sell_i
    global last_buy_or_sell_i
    last_sell_i = i
    last_buy_or_sell_i = i
    stock_price = data_close[i]
    asset_own = asset_own + (stock_price * stock_num)
    stock_num = 0
    asset_share = 0


# {
#             name: 'Mark',
#             coord: ['2013/5/31', 2300],
#             value: 2300,
#             itemStyle: {
#               color: 'rgb(41,60,85)'
#             }

def mark_point_push(name, s, i):
    global mark_point_arr
    mark_json = {}
    coord = [data_all['日期'].loc[i], data_close[i]]
    value = str()
    mark_json["name"] = name
    mark_json["coord"] = coord
    mark_point_arr.append(mark_json)


# main 判断入口
def judge(code, strategy_name):
    global status_buy
    global now
    global data_all
    global data_close
    global data_open
    global data_highest
    global data_lowest
    global data_trend
    global strategy
    data = get_data(code)
    strategy = get_strategy(strategy_name)
    logic_buy_arr = strategy["buyLogic"]
    logic_sell_arr = strategy["sellLogic"]
    judge_init(code)

    # 买卖记录arr
    global buy_arr
    global sell_arr
    global asset_own
    global asset_share
    global stock_num
    buy_arr = [""] * data.shape[0]
    sell_arr = [""] * data.shape[0]
    for i in data.index:
        now = i
        # 根据一天前的涨幅，判断这次买或者卖是否为好操作
        trend_1d = get_trend_str("{trend(1)}")
        status_buy_or_sell = ""
        # 如果可买，只判断logic_buy
        if status_buy:
            # item: {"name":"","value":""}
            for logic_buy_arr_item in logic_buy_arr:
                logic_return = bool(logic_judge(logic_buy_arr_item["value"]))
                # 符合买的逻辑
                if logic_return:
                    status_buy = False
                    buy_arr[i] = (logic_buy_arr_item["name"])
                    mark_point_push(logic_buy_arr_item["name"], '买', i)
                    buy_func(i)
                    status_buy_or_sell = "buy"
                    break

        # 如果状态为 可卖，只判断logic_sell
        else:
            logic_return = True
            # item: {"name":"","value":""}
            for logic_sell_arr_item in logic_sell_arr:
                logic_return = bool(logic_judge(logic_sell_arr_item["value"]))
                # 符合卖的逻辑
                if logic_return:
                    status_buy = True
                    sell_arr[i] = (logic_sell_arr_item["name"])
                    mark_point_push(logic_sell_arr_item["name"], '卖', i)
                    sell_func(i)
                    status_buy_or_sell = "sell"
                    break
        init_result(i)
        # asset_share = stock_num * data_close[i]
        # print(status_buy_or_sell)
        # print("max-buy: " + str(get_after_buy_max_str("{max_after_buy}")))
        # print("stock_price" + str(data_close[i]))
        # print("stock_num" + str(stock_num))
        # print("asset_own:" + str(asset_own))
        # print("asset_share" + str(asset_share))
        # print('-----------------------------------')

    print(buy_arr)
    print(sell_arr)
    print(asset_own_arr)
    print(stock_num_arr)
    print(asset_share_arr)
    print(asset_all_arr)

    df_all = pd.DataFrame(
        {"time": data_time,
         "increase": data_increase,
         "asset_own": asset_own_arr,
         "asset_share": asset_share_arr,
         "stock_num": stock_num_arr,
         "asset_all": asset_all_arr,
         "buy": buy_arr,
         "sell": sell_arr})
    print(df_all)
    df_all.to_csv('df_all.csv')

    judge_result_json = {}
    judge_result_json["time"] = data_time.values.tolist()
    judge_result_json["increase"] = data_increase.values.tolist()
    judge_result_json["asset_own"] = asset_own_arr
    judge_result_json["asset_share"] = asset_share_arr
    judge_result_json["stock_num"] = stock_num_arr
    judge_result_json["asset_all"] = asset_all_arr
    judge_result_json["mark_point"] = mark_point_arr
    print("judge_result_json")
    print(judge_result_json)
    judge_result_file = open('web/stockDetail/' + code + '/judge_result.json', mode='w')
    # ensure_ascii=False 代表中文不转义
    json.dump(judge_result_json, judge_result_file, ensure_ascii=False)
    judge_result_file.close()


def init_result(i):
    global asset_all
    asset_all = asset_own + asset_share
    asset_own_arr.append(asset_own)
    stock_num_arr.append(stock_num)
    asset_share_arr.append(asset_share)
    asset_all_arr.append(asset_all)


# 返回结果：买入记录、卖出记录、实时金额（股票数、own、share）

test_code = '688338'
judge(test_code, "strategy1")

judge_init(test_code)
# t = get_trend_str("{trend(1)}")
# print(t)

# print(get_close_str("({max_after_buy()}-{close()})/{max_after_buy()} < 0.05"))


# print(data_increase)
